// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "demo.h"

#include "common/common.h"
#include "common/actionmanager/actionmanager.h"
#include "common/actionmanager/actioncontainer.h"

#include "base/abstractwidget.h"
#include "base/abstractaction.h"
#include "base/abstractmenu.h"

#include "keyfinder.h"
#include "treesitter.h"
#include "aiderterm.h"

#include <QAction>
#include <QIcon>

const char *D_TSET = "test";

QString absoultPath(QString path) {
    if (path.startsWith("~"))
        return path.replace(0, 1, QDir::homePath());
    return path;
}

void Demo::initialize()
{
}

void Demo::startAiderTerm()
{
    auto editorService = dpfGetService(dpfservice::EditorService);
    auto projectService = dpfGetService(dpfservice::ProjectService);

    QString currentFilePath = editorService->currentFile();
    auto currProjectInfo = projectService->getActiveProjectInfo();
    QString currentWorkspacePath = currProjectInfo.workspaceFolder();
    QString apiType = configWidget->getSetting("aider_api_type");
    QString apiKey = configWidget->getSetting("aider_api_key");

    QString pwd;

    if (currentFilePath.isEmpty())
        return;
    if (currentWorkspacePath.isEmpty())
        pwd = currentFilePath.mid(0, currentFilePath.lastIndexOf('/'));
    else
        pwd = currentWorkspacePath;

    AiderTerm *aiderTerm = new AiderTerm();

    QString aiderPythonBinPath = configWidget->getSetting("aider_python_bin_path");
    aiderTerm->setPythonBinPath(absoultPath(aiderPythonBinPath));
    aiderTerm->resize(800, 600);
    aiderTerm->show();
    aiderTerm->cd(pwd);
    aiderTerm->execute(apiType, apiKey, currentFilePath);
}

void Demo::startKeyFinder()
{
    auto projectService = dpfGetService(dpfservice::ProjectService);
    auto editorService = dpfGetService(dpfservice::EditorService);
    KeyFinder *keyfinder = new KeyFinder();
    QString currentFilePath = editorService->currentFile();
    auto currProjectInfo = projectService->getActiveProjectInfo();
    QString currentWorkspacePath = currProjectInfo.workspaceFolder();
    QString defaultSearchPath;
    if (!currentWorkspacePath.isEmpty())
        defaultSearchPath = currentWorkspacePath;
    else if (!currentFilePath.isEmpty())
        defaultSearchPath = currentFilePath.mid(0, currentFilePath.lastIndexOf('/'));
    else
        defaultSearchPath = "~";
    keyfinder->setDefalutSearchPath(defaultSearchPath);
    keyfinder->resize(1000, 800);
    keyfinder->show();
    QString selectedText = editorService->getSelectedText();
    if (!selectedText.isEmpty())
    {
        keyfinder->setSearchKey(selectedText, false);
        keyfinder->performSearch();
    }
}

void Demo::selectAstNode()
{
    auto windowService = dpfGetService(dpfservice::WindowService);
    auto editorService = dpfGetService(dpfservice::EditorService);
    QString currentFilePath = editorService->currentFile();
    auto curPos = editorService->cursorPosition();

    if (currentFilePath.isEmpty() || curPos.column == -1 || curPos.line == -1)
        return;

    auto currSelectionRange = editorService->selectionRange(currentFilePath);
    if (currSelectionRange.start.column == -1)
        isTssContinue = false;

    if (isTssContinue)
    {
        curPos = tssLastPos;
    }
    else
    {
        tssLastPos = curPos;
        tssNodeSize = -1;
    }

    QString tssPythonBinPath = configWidget->getSetting("tss_python_bin_path");
    TreeSitterSelect tss;
    tss.setPythonBinPath(absoultPath(tssPythonBinPath));
    QStringList args;
    args << currentFilePath << "-r" << QString::number(curPos.line)
         << "-c" << QString::number(curPos.column) << "-e" << QString::number(tssNodeSize);
    PyMsg tssMsg = tss.execute(args);
    if (!tssMsg.error)
    {
        QTextStream tssStream(&tssMsg.msg);
        int startRow, startCol, endRow, endCol, startBytes, endBytes;
        tssStream >> startRow >> startCol >> endRow >> endCol >> startBytes >> endBytes;
        if (tssStream.status() == QTextStream::Ok)
        {
            dpfservice::Edit::Position startPos, endPos;
            dpfservice::Edit::Range selectRange;
            startPos.line = startRow;
            startPos.column = startCol;
            endPos.line = endRow;
            endPos.column = endCol;
            selectRange.start = startPos;
            selectRange.end = endPos;
            tssNodeSize = endBytes - startBytes;
            isTssContinue = true;
            editorService->setSelection(currentFilePath, selectRange);
        }
        else
        {
            windowService->notify(2, "tree-sitter select", "can't to find node range!", {});
            isTssContinue = false;
        }
    }
    else
    {
        windowService->notify(2, "tree-sitter select", tssMsg.msg, {});
        isTssContinue = false;
    }
}

bool Demo::start()
{
    auto windowService = dpfGetService(dpfservice::WindowService);

    if (windowService)
    {
        QString funsionPilotWindowTitle = "FusionPilot";

        QAction *action = new QAction(funsionPilotWindowTitle, this);
        action->setIcon(QIcon::fromTheme(":/demo/images/navigation.png"));
        windowService->addNavigationItem(new AbstractAction(action), Priority::lowest);

        configWidget = new ConfigWidget();
        auto impl = new AbstractWidget(configWidget);
        windowService->registerWidget(funsionPilotWindowTitle, impl);

        // activated when triggered navigation
        connect(action, &QAction::triggered, this, [=]()
                {
                    // show mainwindow
                    windowService->showWidgetAtPosition(funsionPilotWindowTitle, dpfservice::Position::Central, true);
                },
                Qt::DirectConnection);

        QAction *openKeyFinderAction = new QAction(tr("openKeyFinder"));
        auto keyFinderCmd = ActionManager::instance()->registerAction(openKeyFinderAction, "demo.openKeyFinder");
        keyFinderCmd->setDefaultKeySequence(QKeySequence(Qt::ALT + Qt::Key_X)); // 设置快捷键
        connect(openKeyFinderAction, &QAction::triggered, this, &Demo::startKeyFinder, Qt::DirectConnection);

        QAction *selectASTNodeAction = new QAction(tr("selectASTNode"));
        auto selectCmd = ActionManager::instance()->registerAction(selectASTNodeAction, "demo.selectASTNode");
        selectCmd->setDefaultKeySequence(QKeySequence(Qt::ALT + Qt::Key_S)); // 设置快捷键
        connect(selectASTNodeAction, &QAction::triggered, this, &Demo::selectAstNode, Qt::DirectConnection);

        QAction *startAiderTermAction = new QAction(tr("startAiderTerm"));
        auto startAiderCmd = ActionManager::instance()->registerAction(startAiderTermAction, "demo.startAiderTerm");
        startAiderCmd->setDefaultKeySequence(QKeySequence(Qt::ALT + Qt::Key_D)); // 设置快捷键
        connect(startAiderTermAction, &QAction::triggered, this, &Demo::startAiderTerm, Qt::DirectConnection);
    }

    return true;
}

dpf::Plugin::ShutdownFlag Demo::stop()
{
    return Sync;
}
